# -*- coding: utf-8 -*-
"""
Created on Thu Feb  4 22:47:07 2021

@author: 59567
"""
import sys
import os
from pandas import read_excel, concat, to_datetime
import numpy as np
from tjdutils.utils import real_path, TjdDate, check_path, current_time
from tjdutils.fractal_dimension import calculate_fractal_dimension as cal_fd
from copy import deepcopy

sys.path.append('../')


class Corrector():
    def __init__(self, y, y_hf, y_name, method, fd_number=15, fd=1.25, correct=False):
        super(Corrector, self).__init__()
        self.y = y
        self.y.index = [str(t)[:10] for t in self.y.index]
        self.y_hf = deepcopy(y_hf)
        self.y_name = y_name
        self.method = method
        self.correct = correct
        self.y_se = self.y.loc[:, self.y_name]
        self.fd_number = fd_number
        self.fd = fd
        self.y_dict = self.y_se.to_dict()

    def go_correct(self, fd_threhold=1.25, correct=False):
        self.correct = correct
        # 按照之前的monitor写法第六列是三角形面积最小的, 默认第一个
        y_hf_se = self.y_hf.iloc[:, 0]
        print(y_hf_se.name)
        self.y_se.index = to_datetime(self.y_se.index)
        fd_se = cal_fd(self.y_se, self.fd_number)
        fd_se.index = to_datetime(fd_se.index)
        y_hf_se.name = self.y_name
        if self.correct:
            print('correct is True')
            for t in y_hf_se.index:
                d_d = TjdDate(t).dt
                lmld = d_d['lmld']  # 上个月最后一天
                history = self.y.loc[:lmld, self.y_name][-36:]
                # 计算上届和下届
                upper, lower = self._upper_lower(history, self.method, t)
                mld = d_d['mld']  # 本月最后一天
                if mld not in y_hf_se.index:
                    mld = y_hf_se.index[-1]
                v_month_end = y_hf_se[mld]  # 一定会出现的最后一天
                v = y_hf_se[t]
                # print('v', v, 'upper', upper, 'lower', lower)
                if self.method == 'trend':
                    correct_lmld = to_datetime(lmld)
                    if correct_lmld.month not in [12, 1]:
                        print('lmld_month%s' % str(correct_lmld))
                        # 因为y的月度时间序列更新的可能会慢于x特征1-3个月
                        while correct_lmld not in fd_se.index:
                            correct_lmld = to_datetime(TjdDate(correct_lmld).dt['lmld'])
                        if fd_se[correct_lmld] > fd_threhold:
                            if v_month_end > upper:
                                distance = upper - v_month_end
                                y_hf_se[t] = v + distance
                            elif v_month_end < lower:
                                distance = lower - v_month_end
                                y_hf_se[t] = v + distance
                    else:
                        print(t)
                        print('二月不修')
                else:
                    if v_month_end > upper:
                        distance = upper - v_month_end
                        y_hf_se[t] = v + distance
                    elif v_month_end < lower:
                        distance = lower - v_month_end
                        y_hf_se[t] = v + distance
        self.y_correct = y_hf_se
        return y_hf_se

    def go_connect(self):
        self.y_correct.index = to_datetime(self.y_correct.index)
        y_connect = deepcopy(self.y_correct)
        print('y_correct_shape', self.y_correct.shape)
        print('y_connect_shape', y_connect.shape)

        long_index = [self.y_se.index[i] for i, v in enumerate(list(self.y_se)) if not np.isnan(v)]
        short_index = [str(s)[:10] for s in long_index]
        y_exist_index = long_index + short_index
        for t in self.y_correct.index:
            tjd_date = TjdDate(t)
            day_from = tjd_date.today.day
            day_all = tjd_date.month_last_day.day
            day_left = day_all - day_from
            lmld = tjd_date.dt['lmld']
            if lmld in y_exist_index:
                y_lmld = self.y.loc[lmld, self.y_name]
            else:
                y_lmld = self.y_correct[to_datetime(lmld)]
            y_connect[t] = (y_lmld * day_left + self.y_correct[t] * day_from) / day_all
        return y_connect

    def _upper_lower(self, y_history, method, t):
        y_last_period = y_history[-1]
        yll = y_history[-2]
        if method == 'abs':
            upper = np.max(y_history)
            lower = np.min(y_history)
        elif method == 'sigma3':
            std = np.std(y_history)
            upper = y_last_period + 3 * std
            lower = y_last_period - 3 * std
        elif method == 'diff':
            upper = y_last_period + np.max(np.diff(y_history))
            lower = y_last_period + np.min(np.diff(y_history))
        elif method == 'trend':
            trend = y_last_period - yll
            future = y_last_period + trend
            std = np.std(y_history)
            upper = future + 0.02 * std
            lower = future - 0.02 * std
        elif method == 'auto':
            pass
        return (upper, lower)


def get_y_name(path):
    if '/' in list(path):
        path = os.path.split(path)[-1]
    return path[:-27]


def more_y():
    ys = []
    dir_path = check_path('../output/monitor/')
    paths = os.listdir(dir_path)
    y = read_excel(real_path('y集合.xlsx'), index_col=0)
    for path in paths:
        p = os.path.join(dir_path, path)
        y_name = get_y_name(p)
        y_df = read_excel(p, index_col=0)
        y_hf = y_df.iloc[:, [6]]
        ys.append(Corrector(y, y_hf, y_name, 'sigma3').y_connect)
    ys_df = concat(ys, axis=1)
    try:
        ys_df.to_excel('../output/' + current_time() + '.xlsx')
    except:
        ys_df.to_excel('../../output/' + current_time() + '.xlsx')
    return ys_df


def go_correct_hf_df(ctor, hf_df, fd_threhold):
    # 按照之前的monitor写法第六列是三角形面积最小的, 默认第一个
    y_hf_se = ctor.y_hf.iloc[:, 0]
    print(y_hf_se.name)
    ctor.y_se.index = to_datetime(ctor.y_se.index)
    fd_se = cal_fd(ctor.y_se, ctor.fd_number)
    fd_se.index = to_datetime(fd_se.index)
    y_hf_se.name = ctor.y_name
    for t in y_hf_se.index:
        d_d = TjdDate(t).dt
        lmld = d_d['lmld']  # 上个月最后一天
        history = ctor.y.loc[:lmld, ctor.y_name][-36:]
        upper, lower = ctor._upper_lower(history, ctor.method, t)
        mld = d_d['mld']  # 本月最后一天
        if mld not in y_hf_se.index:
            mld = y_hf_se.index[-1]
        v_month_end = y_hf_se[mld]  # 一定会出现的最后一天
        v = y_hf_se[t]
        if ctor.method == 'trend':
            correct_lmld = to_datetime(lmld)
            while correct_lmld not in fd_se.index:
                print('form :', correct_lmld)
                correct_lmld = to_datetime(TjdDate(correct_lmld).dt['lmld'])
                print('to :', correct_lmld)
            print(fd_se.index)
            if fd_se[correct_lmld] > fd_threhold:
                if v_month_end > upper:
                    distance = upper - v_month_end
                    y_hf_se[t] = v + distance
                elif v_month_end < lower:
                    distance = lower - v_month_end
                    y_hf_se[t] = v + distance
        else:
            if v_month_end > upper:
                distance = upper - v_month_end
                y_hf_se[t] = v + distance
            elif v_month_end < lower:
                distance = lower - v_month_end
                y_hf_se[t] = v + distance


if __name__ == "__main__":
    ys = more_y()
